package pl.vm.service;

import java.util.List;

import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;


import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import pl.vm.dao.SeazonDao;
import pl.vm.exceptions.CannotRemoveSeazonException;
import pl.vm.exceptions.CannotRemoveTeamException;
import pl.vm.exceptions.SeazonAlreadyExistException;
import pl.vm.exceptions.TeamAlreadyExistException;
import pl.vm.exceptions.TeamNotExistException;
import pl.vm.model.OfficialTeam;
import pl.vm.model.Seazon;

@Transactional
@Service
public class SeazonService {

	@Autowired
	private SeazonDao seazonDao;
	@Autowired
	private SessionFactory sessionFactory;
	
	public List<Seazon> getSeazons() {
		return seazonDao.loadAll();
	}
	
	public void createNewSeazon(String seazonName) throws SeazonAlreadyExistException {
		List<Seazon> seazons = getSeazons();
		for (Seazon seazon : seazons) {
			if (seazon.getName().equals(seazonName)) {
				throw new SeazonAlreadyExistException("Seazon: " + seazonName + " already exist");
			}
		}
		Seazon newSeazon = new Seazon(seazonName);
		seazonDao.persist(newSeazon);
	}
	
	public void removeSeazon(long seazonId) throws CannotRemoveSeazonException {
		Session session = sessionFactory.getCurrentSession();
		Seazon seazon = seazonDao.get(seazonId);
		Query query = session.getNamedQuery("officialTeamSize");
		query.setLong("id", seazonId);
//		Query query = session.createQuery("select S.officialTeams.size from Seazon S where S.id = " + seazonId);
		Integer officialTeams = (Integer) query.uniqueResult();
		if (officialTeams > 0) {
			throw new CannotRemoveSeazonException("There are already official teams added to this seazon. Remove it first.");
		}
		query = session.createQuery("select S.rounds.size from Seazon S where S.id = " + seazonId);		
		Integer rounds = (Integer) query.uniqueResult();
		if (rounds > 0) {
			throw new CannotRemoveSeazonException("There are already rounds added to this seazon. Remove it first.");			
		}
		//TODO check if seazon is eligible for deletion 
		// seazonDao.delete(seazon);
	}
	
	public Seazon getSeazon(long id) {
		Seazon seazon = seazonDao.get(id);
		return seazon;
	}
		
	public void addOfficialTeam(OfficialTeam team, Long seazonId) throws TeamAlreadyExistException {
		Seazon seazon = seazonDao.get(seazonId);
		List<OfficialTeam> teams = seazon.getOfficialTeams();
		if (!teams.contains(team)) {
			teams.add(team);
		} else {
			throw new TeamAlreadyExistException("Team: " + team.getName() + ", already exists.");
		}
		seazonDao.merge(seazon);
	}
	
	public void removeOfficialTeam(OfficialTeam team, Long seazonId) throws TeamNotExistException, CannotRemoveTeamException {
		Seazon seazon = seazonDao.get(seazonId);
		List<OfficialTeam> teams = seazon.getOfficialTeams();
		if (teams.contains(team)) {
			if (team.getPlayers().size() == 0) {
				teams.remove(team);
			} else {
				throw new CannotRemoveTeamException("Team: " + team.getName() + " cannot be removed, because it contains players. " +
						"Remove players before removing team.");
			}
		} else {
			throw new TeamNotExistException("Team: " + team.getName() + ", does not exists.");
		}
		seazonDao.merge(seazon);
	}
}
